#!/usr/bin/env python
# -*- coding: utf-8 -*-

import logging

import web
import framework
import urls

__author__ = 'Michael Liao (askxuefeng@gmail.com)'

def _load_domain(domain):
    web.ctx.db = framework.connect()
    cs = list(web.ctx.db.query('select * from kbcustomer where domain=$d', vars=dict(d=domain)))
    if cs:
        return cs[0]
    raise web.notfound('404 No such customer')

class PageHandler(object):

    def __init__(self):
        self.mapping = {}
        for s in dir(urls):
            f = getattr(urls, s)
            if callable(f) and getattr(f, 'handler', False):
                self.mapping[getattr(f, '__name__', '')] = f
        logging.info('Mapping: %s' % str(self.mapping))

    def GET(self, path):
        logging.info('GET /%s' % path)
        return self._handle(path)

    def POST(self, path):
        logging.info('POST /%s' % path)
        return self._handle(path)

    def _extract(self, path):
        # extract domain from /example.com/func/arg1/arg2:
        ss = path.split('/')
        domain = ss[0]
        # check domain:
        web.ctx.customer = _load_domain(domain=domain)
        func = 'index'
        args = ()
        if len(ss)>1:
            func = ss[1]
        if len(ss)>2:
            args = ss[2:]
        f = self.mapping.get(func, None)
        if f is None:
            raise web.notfound('404 Page not found')
        n = len(args)
        if n < f.min_args or n > f.max_args:
            raise web.notfound('invalid args')
        logging.info('Invoke %s%s' % (func, str(args)))
        return func, args

    def _handle(self, path):
        if path=='':
            func = 'welcome'
            args = ()
        elif path.startswith('auth_'):
            func = path
            args = ()
        else:
            func, args = self._extract(path)
        # call function:
        logging.info('call %s%s' % (func, str(args)))
        f = self.mapping.get(func, None)
        if f is None:
            raise web.notfound('404 Page not found')
        n = len(args)
        if n < f.min_args or n > f.max_args:
            raise web.notfound('invalid args')
        logging.info('Invoke %s%s' % (func, str(args)))
        web.ctx.db = framework.connect()
        web.ctx.user = framework.extract_oauth_cookie(web.cookies().get(framework.COOKIE_NAME, ''))
        try:
            return f(*args)
        except framework.WebError, e:
            return e.message
        except BaseException, e:
            raise

app = web.application(('/(.*)', 'PageHandler'), globals())

if __name__ == '__main__':
    app.run()
else:
    application = app.wsgifunc()
